#include "GameApp.h"


GameApp::GameApp(void)
{
	player_one = new Player("player1.player");
	my_components.push_back(player_one);
	model_view = new AlphaMatrixStack();
	projection = new AlphaMatrix();
	projection->loadPerspective(AlphaMath::DegToRadians(35.0f), 4.0f / 3.0f, 0.1f, 10000.0f);
	gc = new Camera();
	t = new terrain(64,50.0f);
	test = new float[4];

	current_unit = my_components[0]->getComponent(0);
	current_unit_type = FACTORY;
	button_hovered = 0;
	b_h = false;
	r_move = false;


}

GameApp::GameApp(char* fname)
{
}

GameApp::~GameApp(void)
{
}

void GameApp::initMe(GameComponent* g)
{

	initTexBuffer();

	GLfloat quad_coords[] = {	-1.0 , 1.0,
								-1.0 , -1.0,
								 1.0 , -1.0,
								 1.0 , 1.0,
								-1.0 , 1.0,
								 1.0 , -1.0
								 };
	glGenVertexArrays(1, &vao);
	// Setup Vertex 
	glBindVertexArray(vao);
	glGenBuffers(1, &vbo);
	
	// VBO for vertex data
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), quad_coords, GL_STATIC_DRAW);
	glVertexAttribPointer((GLuint)0, 2, GL_FLOAT, GL_FALSE, 0, 0); 
	glEnableVertexAttribArray(0);

	program = Utilities::useShader("program.shader");

	ov_tex_1 = Utilities::useTexture("g_screen_build_1.png");
	ov_tex_2 = Utilities::useTexture("g_screen_build_2.png");

	ov_tex_3 = Utilities::useTexture("g_screen_unit_2.png");
	ov_tex_4 = Utilities::useTexture("g_screen_unit_1.png");
}

void GameApp::keyBoardHandler(SDL_Event e)
{
	if(e.type == SDL_KEYDOWN)
	{
		switch(e.key.keysym.sym)
		{
		//case 'a':
		//	((MoveableComponent*)current_unit->getComponent(2))->setMove(WEST);
		//	break;
		//case 'd':
		//	((MoveableComponent*)current_unit->getComponent(2))->setMove(EAST);
		//	break;
		//case 's':
		//	((MoveableComponent*)current_unit->getComponent(2))->setMove(SOUTH);
		//	break;
		//case 'w':
		//	((MoveableComponent*)current_unit->getComponent(2))->setMove(NORTH);
		//	break;
		//case 'p':
		//	((MoveableComponent*)current_unit->getComponent(2))->setMove(NONE);
		//	break;
		case SDLK_LEFT:
			gc->strafeLeft();
			break;
		case SDLK_RIGHT:
			gc->strafeRight();
			break;
		case SDLK_DOWN:
			gc->moveForward();
			break;
		case SDLK_UP:
			gc->moveBackward();
			break;
		case 'm':
			gc->moveIn();
			break;
		case 'n':
			gc->moveOut();
			break;
		}
	}
}

void GameApp::render()
{
	model_view->pushMatrix();
		model_view->pushMatrix();
			gc->setCamera(model_view);
			glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
			GLenum buffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
			glDrawBuffers(2, buffers);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
				t->renderMe(model_view,projection);
				renderMe(model_view, projection);
				renderChildren(model_view, projection);
		model_view->popMatrix();	
	model_view->popMatrix();

	glCopyTexImage2D(fbo_tex, 0, GL_RGBA, 0, 0, 800, 600, 0);
	glCopyTexImage2D(fbo_ID_tex, 0, GL_RGBA, 0, 0, 800, 600, 0);

	glReadBuffer(buffers[1]);
	SDL_GetMouseState(&mouse_x, &mouse_y);
	mouse_y = (mouse_y - 600) * -1;
	button_hovered = 0;
	if(mouse_x > 475 && mouse_x < 725)
	{
		if(mouse_y > 15 && mouse_y < 60)
		{
			button_hovered = 1;
		}
	}
	
	glReadPixels(mouse_x, mouse_y, 1, 1, GL_RGBA, GL_FLOAT, test);

	//current_identifier = floor((1 / test[0]) + 0.5f);
	current_identifier = test[0];

	/*for(int i = 0; i < 3; i++)
	{
		test[i] = test[i] - 0.5;
		test[i] = test[i] * 2;
		test[i] = test[i] * 1000;
	}*/

	
	//std::cout << mouse_x <<"............"<< mouse_y << std::endl;
	//std::cout << current_identifier << std::endl;
	std::cout << test[0] << "..." << test[1] << "..." << test[2] << "..." << test[3] << std::endl;

	for(unsigned int i = 0; i < my_components.size(); i++)
	{
		for(unsigned int j = 0; j < my_components[i]->my_components.size(); j++)
		{
			for(unsigned int k = 0; k < my_components[i]->my_components[j]->my_components.size(); k++)
			{
				if((int)test[3] == 1)
				{
					if(current_identifier == ((ViewableComponent*)my_components[i]->my_components[j]->my_components[k])->getID())
					{
						((ViewableComponent*)my_components[i]->my_components[j]->my_components[1])->setHoveredTrue();
					}
				}
			}
		}
	}

	glUseProgram(program);

	GLuint uniformIndex = glGetUniformLocation(program, "first_output");
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, fbo_ID_tex);
	glUniform1i(uniformIndex, 0);

	if(current_unit_type == FACTORY)
	{
		switch(button_hovered)
		{
		case 1:
			uniformIndex = glGetUniformLocation(program, "o_lay");
			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_2D, ov_tex_2);
			glUniform1i(uniformIndex, 1);
			break;
		default:
			uniformIndex = glGetUniformLocation(program, "o_lay");
			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_2D, ov_tex_1);
			glUniform1i(uniformIndex, 1);
		}
	}
	else
	{
		if(button_hovered || r_move)
		{
			uniformIndex = glGetUniformLocation(program, "o_lay");
			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_2D, ov_tex_3);
			glUniform1i(uniformIndex, 1);
		}
		else
		{
			uniformIndex = glGetUniformLocation(program, "o_lay");
			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_2D, ov_tex_4);
			glUniform1i(uniformIndex, 1);
		}
		/*switch(button_hovered)
		{
			case 1:
				uniformIndex = glGetUniformLocation(program, "o_lay");
				glActiveTexture(GL_TEXTURE1);
				glBindTexture(GL_TEXTURE_2D, ov_tex_3);
				glUniform1i(uniformIndex, 1);
				break;
			default:
				uniformIndex = glGetUniformLocation(program, "o_lay");
				glActiveTexture(GL_TEXTURE1);
				glBindTexture(GL_TEXTURE_2D, ov_tex_4);
				glUniform1i(uniformIndex, 1);
		}*/
	}
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);	
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glBindVertexArray(vao);
	glDrawArrays(GL_TRIANGLES, 0, 6);
}

void GameApp::initTexBuffer()
	{
		 // "handles" for framebuffer and it's texture
		glGenFramebuffers(1, &fbo);
		glBindFramebuffer(GL_FRAMEBUFFER, fbo);

		//generate texture ID
		glGenTextures(1, &fbo_tex);
		//bind texture and set parameters.
		glBindTexture(GL_TEXTURE_2D, fbo_tex);

		
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 800, 600, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo_tex, 0);

		//generate texture ID
		glGenTextures(1, &fbo_ID_tex);
		glBindTexture(GL_TEXTURE_2D, fbo_ID_tex);

		
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, 800, 600, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, fbo_ID_tex, 0);

		// Generate depthBuffer
		glGenRenderbuffers(1, &fbo_depth);
		glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
		glBindRenderbuffer(GL_RENDERBUFFER, fbo_depth);
		glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 800, 600);
		glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo_depth);
		
		
		GLenum valid = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
		if(valid != GL_FRAMEBUFFER_COMPLETE)
				std::cout << "Framebuffer object not complete" << std::endl;
		if(valid == GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)
				std::cout << "Framebuffer incomplete attachment" << std::endl;
		if(valid == GL_FRAMEBUFFER_UNSUPPORTED)
				std::cout << "FBO attachments unsoported" << std::endl;

	}

void GameApp::captureMouse(SDL_Event e)
{
	int temp = 0;
	if(e.type == SDL_MOUSEBUTTONDOWN)
	{
		if(e.button.button == SDL_BUTTON_LEFT)
		{
			if(test[3] == 0.0)
			{
				switch(current_unit_type)
				{
				case FACTORY:
					std::cout << "Build Tank..." << std::endl;
					if(button_hovered)
					{
						((Player*)player_one)->addUnit("unit2.ent");
						temp = player_one->getNumC() - 1;
						player_one->getComponent(temp)->init(player_one);
						((MoveableComponent*)player_one->getComponent(temp)->getComponent(2))->setDestination(new AlphaVector(-130, 0.0,200, 1.0));
					}
					break;
				case TANK:
					if(r_move)
					{
						std::cout << "Move..." << std::endl;
						((MoveableComponent*)current_unit->getComponent(2))->setDestination(new AlphaVector(test[0], 0.0, (-test[2] / 36.0) * 50.0, 1.0));
						r_move = false;
					}
					if(button_hovered)
					{
						r_move = !r_move;
					}

				}
				
			}	
				for(unsigned int i = 0; i < my_components.size(); i++)
				{
					for(unsigned int j = 0; j < my_components[i]->my_components.size(); j++)
					{
						for(unsigned int k = 0; k < my_components[i]->my_components[j]->my_components.size(); k++)
						{
							if(current_identifier == ((ViewableComponent*)my_components[i]->my_components[j]->my_components[k])->getID())
							{
								if(current_identifier == 2)
								{
									current_unit_type = FACTORY;
								}
								else
								{
									current_unit_type = TANK;
								}
								current_unit = my_components[i]->my_components[j];
							}
						}
					}
				}
		}
	}
}